<h2>Why is this an issue?</h2>
<p>There’s no point in chaining multiple <code>OrderBy</code> calls in a LINQ; only the last one will be reflected in the result because each
subsequent call completely reorders the list. Thus, calling <code>OrderBy</code> multiple times is a performance issue as well, because all of the
sorting will be executed, but only the result of the last sort will be kept.</p>
<h2>How to fix it</h2>
<p>Instead, use <code>ThenBy</code> for each call after the first.</p>
<h3>Code examples</h3>
<h4>Noncompliant code example</h4>
<pre data-diff-id="1" data-diff-type="noncompliant">
var x = personList
  .OrderBy(person =&gt; person.Age)
  .OrderBy(person =&gt; person.Name)  // Noncompliant
  .ToList();  // x is sorted by Name, not sub-sorted
</pre>
<h4>Compliant solution</h4>
<pre data-diff-id="1" data-diff-type="compliant">
var x = personList
  .OrderBy(person =&gt; person.Age)
  .ThenBy(person =&gt; person.Name)
  .ToList();
</pre>
<h2>Resources</h2>
<h3>Benchmarks</h3>
<table>
  <colgroup>
    <col style="width: 20%;">
    <col style="width: 20%;">
    <col style="width: 20%;">
    <col style="width: 20%;">
    <col style="width: 20%;">
  </colgroup>
  <thead>
    <tr>
      <th>Method</th>
      <th>Runtime</th>
      <th>Mean</th>
      <th>StdDev</th>
      <th>Allocated</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><p>OrderByAge</p></td>
      <td><p>.NET 9.0</p></td>
      <td><p>12.84 ms</p></td>
      <td><p>0.804 ms</p></td>
      <td><p>1.53 MB</p></td>
    </tr>
    <tr>
      <td><p>OrderByAgeOrderBySize</p></td>
      <td><p>.NET 9.0</p></td>
      <td><p>24.08 ms</p></td>
      <td><p>0.267 ms</p></td>
      <td><p>3.05 MB</p></td>
    </tr>
    <tr>
      <td><p>OrderByAgeThenBySize</p></td>
      <td><p>.NET 9.0</p></td>
      <td><p>18.58 ms</p></td>
      <td><p>0.747 ms</p></td>
      <td><p>1.91 MB</p></td>
    </tr>
    <tr>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
    </tr>
    <tr>
      <td><p>OrderByAge</p></td>
      <td><p>.NET Framework 4.8.1</p></td>
      <td><p>22.99 ms</p></td>
      <td><p>0.228 ms</p></td>
      <td><p>1.53 MB</p></td>
    </tr>
    <tr>
      <td><p>OrderByAgeOrderBySize</p></td>
      <td><p>.NET Framework 4.8.1</p></td>
      <td><p>44.90 ms</p></td>
      <td><p>0.581 ms</p></td>
      <td><p>4.3 MB</p></td>
    </tr>
    <tr>
      <td><p>OrderByAgeThenBySize</p></td>
      <td><p>.NET Framework 4.8.1</p></td>
      <td><p>31.72 ms</p></td>
      <td><p>0.402 ms</p></td>
      <td><p>1.91 MB</p></td>
    </tr>
  </tbody>
</table>
<h4>Glossary</h4>
<ul>
  <li> <a href="https://en.wikipedia.org/wiki/Arithmetic_mean">Mean</a> </li>
  <li> <a href="https://en.wikipedia.org/wiki/Standard_deviation">Standard Deviation</a> </li>
</ul>
<p>The results were generated by running the following snippet with <a href="https://github.com/dotnet/BenchmarkDotNet">BenchmarkDotNet</a>:</p>
<pre>
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public int Size { get; set; }
}

private Random random = new Random(1);
private Consumer consumer = new Consumer();
private Person[] array;

[Params(100_000)]
public int N { get; set; }

[GlobalSetup]
public void GlobalSetup()
{
    array = Enumerable.Range(0, N).Select(x =&gt; new Person
    {
      Name = Path.GetRandomFileName(),
      Age = random.Next(0, 100),
      Size = random.Next(0, 200)
    }).ToArray();
}

[Benchmark(Baseline = true)]
public void OrderByAge() =&gt;
    array.OrderBy(x =&gt; x.Age).Consume(consumer);

[Benchmark]
public void OrderByAgeOrderBySize() =&gt;
    array.OrderBy(x =&gt; x.Age).OrderBy(x =&gt; x.Size).Consume(consumer);

[Benchmark]
public void OrderByAgeThenBySize() =&gt;
    array.OrderBy(x =&gt; x.Age).ThenBy(x =&gt; x.Size).Consume(consumer);
</pre>
<p>Hardware configuration:</p>
<pre>
BenchmarkDotNet v0.14.0, Windows 10 (10.0.19045.5247/22H2/2022Update)
Intel Core Ultra 7 165H, 1 CPU, 22 logical and 16 physical cores
  [Host]               : .NET Framework 4.8.1 (4.8.9282.0), X64 RyuJIT VectorSize=256
  .NET 9.0             : .NET 9.0.0 (9.0.24.52809), X64 RyuJIT AVX2
  .NET Framework 4.8.1 : .NET Framework 4.8.1 (4.8.9282.0), X64 RyuJIT VectorSize=256
</pre>

